xmlss 1.0.0.rc.1 → 1.0.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,5 +3,7 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in xmlss.gemspec
4
4
  gemspec
5
5
 
6
+ gem 'bundler', '~>1.1'
6
7
  gem 'rake', '~>0.9.2'
8
+ gem "whysoslow", "~> 0.0"
7
9
  gem 'ruby-prof'
data/Gemfile.lock CHANGED
@@ -1,30 +1,33 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- xmlss (1.0.0.rc.1)
4
+ xmlss (1.0.0.rc.2)
5
5
  enumeration (~> 1.3)
6
- undies (~> 2.2.1)
6
+ undies (~> 3.0.0.rc.1)
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- ansi (1.4.1)
11
+ ansi (1.4.2)
12
12
  assert (0.7.3)
13
13
  assert-view (~> 0.5)
14
- assert-view (0.5.0)
14
+ assert-view (0.6.0)
15
15
  ansi (~> 1.3)
16
- undies (~> 2.0)
17
16
  enumeration (1.3.1)
18
17
  rake (0.9.2)
19
18
  ruby-prof (0.10.8)
20
- undies (2.2.1)
19
+ undies (3.0.0.rc.1)
20
+ whysoslow (0.0.2)
21
+ ansi (~> 1.4)
21
22
 
22
23
  PLATFORMS
23
24
  ruby
24
25
 
25
26
  DEPENDENCIES
26
- assert (~> 0.6)
27
- bundler (~> 1.0)
27
+ assert (~> 0.7.3)
28
+ assert-view (~> 0.6)
29
+ bundler (~> 1.1)
28
30
  rake (~> 0.9.2)
29
31
  ruby-prof
32
+ whysoslow (~> 0.0)
30
33
  xmlss!
data/Rakefile CHANGED
@@ -4,27 +4,46 @@ include Assert::RakeTasks
4
4
  require 'bundler'
5
5
  Bundler::GemHelper.install_tasks
6
6
 
7
- task :default => :run_all
8
-
9
- desc "Run the example workbook builds."
10
- task :run_examples do
11
- require 'examples/simple'
12
- require 'examples/layout'
13
- require 'examples/text'
14
- require 'examples/styles'
15
- end
7
+ task :default => :build
8
+
9
+ namespace :bench do
10
+
11
+ desc "Run the bench script."
12
+ task :run do
13
+ require 'bench/bench_runner'
14
+ XmlssBenchRunner.new(1000).run
15
+ end
16
+
17
+ desc "Run the profiler on 1000 rows."
18
+ task :profiler do
19
+ require 'bench/profiler_runner'
16
20
 
17
- desc "Run the profiler on 1000 rows."
18
- task :run_profiler do
19
- require 'bench/profiler_runner'
21
+ runner = XmlssProfilerRunner.new(1000)
22
+ runner.print_flat(STDOUT, :min_percent => 1)
23
+ end
24
+
25
+ desc "Run the example workbook builds."
26
+ task :examples do
27
+ require 'examples/simple'
28
+ require 'examples/layout'
29
+ require 'examples/text'
30
+ require 'examples/styles'
31
+ end
32
+
33
+ desc "Run all the tests, then the profiler, then the bench."
34
+ task :all do
35
+ Rake::Task['test'].invoke
36
+ puts
37
+ Rake::Task['bench:profiler'].invoke
38
+ puts
39
+ Rake::Task['bench:run'].invoke
40
+ puts
41
+ Rake::Task['bench:examples'].invoke
42
+ end
20
43
 
21
- runner = XmlssProfilerRunner.new(1000)
22
- runner.print_flat(STDOUT, :min_percent => 3)
23
44
  end
24
45
 
25
- desc "Run all the tests, then the example builds, then the profiler."
26
- task :run_all do
27
- Rake::Task['test'].invoke
28
- Rake::Task['run_examples'].invoke
29
- Rake::Task['run_profiler'].invoke
46
+ task :bench do
47
+ Rake::Task['bench:run'].invoke
30
48
  end
49
+
@@ -0,0 +1,42 @@
1
+ require 'whysoslow'
2
+ require 'xmlss'
3
+
4
+ class XmlssBenchRunner
5
+
6
+ attr_reader :result
7
+
8
+ def initialize(n)
9
+ @build = Proc.new do
10
+ Xmlss::Workbook.new(Xmlss::Writer.new(:pp => 2), &Proc.new do
11
+ worksheet("5 columns, #{n} rows") {
12
+ column
13
+ column
14
+ column
15
+ column
16
+ column
17
+
18
+ n.times do |i|
19
+ row {
20
+ # put data into the row (infer type)
21
+ [1, "text", 123.45, "0001267", "$45.23"].each do |data_value|
22
+ cell { data data_value }
23
+ end
24
+ }
25
+ end
26
+ }
27
+ end).to_file("./bench/profiler_#{n}.xml")
28
+ end
29
+
30
+ @printer = Whysoslow::DefaultPrinter.new({
31
+ :title => "#{n} rows",
32
+ :verbose => true
33
+ })
34
+
35
+ @runner = Whysoslow::Runner.new(@printer)
36
+ end
37
+
38
+ def run
39
+ @runner.run &@build
40
+ end
41
+
42
+ end
data/examples/layout.xml CHANGED
@@ -1,7 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
3
3
  <Styles>
4
-
5
4
  </Styles>
6
5
  <Worksheet ss:Name="first">
7
6
  <Table>
data/examples/simple.xml CHANGED
@@ -1,7 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
3
3
  <Styles>
4
-
5
4
  </Styles>
6
5
  <Worksheet ss:Name="1 row, 5 columns">
7
6
  <Table>
@@ -7,8 +7,6 @@ module Xmlss::Element
7
7
  def self.writer; :cell; end
8
8
 
9
9
  attr_accessor :index, :style_id, :formula, :href, :merge_across, :merge_down
10
- alias_method :style_i_d, :style_id
11
- alias_method :h_ref, :href
12
10
 
13
11
  attr_accessor :data
14
12
 
@@ -21,18 +19,14 @@ module Xmlss::Element
21
19
  :error => "Error"
22
20
  }
23
21
 
24
- def initialize(*args, &build)
22
+ def initialize(*args)
25
23
  attrs = args.last.kind_of?(::Hash) ? args.pop : {}
26
24
 
27
- self.data = args.last.nil? ? (attrs[:data] || "") : args.last
28
- self.type = attrs[:type] unless attrs[:type].nil?
25
+ self.data = [args.last, attrs.delete(:data), ''].reject{|v| v.nil?}.first
26
+ self.merge_across = attrs.delete(:merge_across) || 0
27
+ self.merge_down = attrs.delete(:merge_down) || 0
29
28
 
30
- self.index = attrs[:index]
31
- self.style_id = attrs[:style_id]
32
- self.formula = attrs[:formula]
33
- self.href = attrs[:href]
34
- self.merge_across = attrs[:merge_across] || 0
35
- self.merge_down = attrs[:merge_down] || 0
29
+ attrs.keys.each { |k| self.send("#{k}=", attrs[k]) }
36
30
  end
37
31
 
38
32
  def data=(v)
@@ -49,27 +43,38 @@ module Xmlss::Element
49
43
  end
50
44
  end
51
45
 
52
- [:index, :merge_across, :merge_down].each do |meth|
53
- define_method("#{meth}=") do |value|
54
- if value && !value.kind_of?(::Fixnum)
55
- raise ArgumentError, "must specify #{meth} as a Fixnum"
56
- end
57
- instance_variable_set("@#{meth}", value && value <= 0 ? nil : value)
46
+ def index=(value)
47
+ if value && !value.kind_of?(::Fixnum)
48
+ raise ArgumentError, "must specify `index` as a Fixnum"
58
49
  end
50
+ @index = (value && value <= 0 ? nil : value)
51
+ end
52
+
53
+ def merge_across=(value)
54
+ if value && !value.kind_of?(::Fixnum)
55
+ raise ArgumentError, "must specify `merge_across` as a Fixnum"
56
+ end
57
+ @merge_across = (value && value <= 0 ? nil : value)
58
+ end
59
+
60
+ def merge_down=(value)
61
+ if value && !value.kind_of?(::Fixnum)
62
+ raise ArgumentError, "must specify `merge_down` as a Fixnum"
63
+ end
64
+ @merge_down = (value && value <= 0 ? nil : value)
59
65
  end
60
66
 
61
67
  private
62
68
 
63
69
  def data_type(v)
64
- case v
65
- when ::Numeric
70
+ if v.kind_of?(::String) || v.kind_of?(::Symbol)
71
+ :string
72
+ elsif v.kind_of?(::Numeric)
66
73
  :number
67
- when ::Date, ::Time
74
+ elsif v.kind_of?(::Date) || v.kind_of?(::Time)
68
75
  :date_time
69
- when ::TrueClass, ::FalseClass
76
+ elsif v.kind_of?(::TrueClass) || v.kind_of?(::FalseClass)
70
77
  :boolean
71
- when ::String, ::Symbol
72
- :string
73
78
  else
74
79
  :string
75
80
  end
@@ -5,7 +5,6 @@ module Xmlss::Element
5
5
  def self.writer; :column; end
6
6
 
7
7
  attr_accessor :style_id, :width, :auto_fit_width, :hidden
8
- alias_method :style_i_d, :style_id
9
8
 
10
9
  def initialize(attrs={})
11
10
  self.style_id = attrs[:style_id]
@@ -5,7 +5,6 @@ module Xmlss::Element
5
5
  def self.writer; :row; end
6
6
 
7
7
  attr_accessor :style_id, :height, :auto_fit_height, :hidden
8
- alias_method :style_i_d, :style_id
9
8
 
10
9
  def initialize(attrs={})
11
10
  self.style_id = attrs[:style_id]
@@ -24,7 +24,7 @@ module Xmlss::Element
24
24
  @name = if !value.nil? && !value.to_s.empty?
25
25
  sanitized_name(value.to_s)
26
26
  else
27
- "" # TODO: make sure you don't write a worksheet with no sanitized_name
27
+ ""
28
28
  end
29
29
  end
30
30
 
@@ -12,7 +12,7 @@ module Xmlss
12
12
  def initialize(writer, markup_type)
13
13
  @stack = []
14
14
  @writer = writer
15
- @markup_type = markup_type
15
+ @markup_type = markup_type.to_s
16
16
  @written_level = 0
17
17
  end
18
18
 
@@ -24,44 +24,38 @@ module Xmlss
24
24
  alias_method :current, :last
25
25
  alias_method :level, :size
26
26
 
27
+ def using(element, &block)
28
+ push(element)
29
+ (block || Proc.new {}).call
30
+ pop
31
+ end
32
+
27
33
  def push(element)
28
34
  if @written_level < level
29
- open(current)
35
+ write(current)
36
+ @writer.push(@markup_type)
37
+ @written_level += 1
30
38
  end
31
39
  @stack.push(element)
32
40
  end
33
41
 
34
42
  def pop
35
43
  if !empty?
36
- if @written_level < level
37
- @stack.pop.tap { |elem| write(elem) }
38
- else
39
- @stack.pop.tap { |elem| close(elem) }
40
- end
44
+ @written_level < level ? write(@stack.pop) : close(@stack.pop)
41
45
  end
42
46
  end
43
47
 
44
- def using(element, &block)
45
- push(element)
46
- (block || Proc.new {}).call
47
- pop
48
- end
49
-
50
48
  private
51
49
 
52
- def open(element)
53
- write(element)
54
- @writer.push(@markup_type)
55
- @written_level += 1
56
- end
57
-
58
50
  def close(element)
59
51
  @writer.pop(@markup_type)
60
52
  @written_level -= 1
53
+ element
61
54
  end
62
55
 
63
56
  def write(element)
64
57
  @writer.write(element)
58
+ element
65
59
  end
66
60
 
67
61
  end
@@ -15,7 +15,6 @@ module Xmlss::Style
15
15
  def self.writer; :style; end
16
16
 
17
17
  attr_reader :id
18
- alias_method :i_d, :id
19
18
 
20
19
  def initialize(id)
21
20
  raise ArgumentError, "please choose an id for the style" if id.nil?
@@ -16,10 +16,8 @@ module Xmlss::Style
16
16
  :subscript => 'Subscript',
17
17
  :superscript => 'Superscript'
18
18
  }
19
- alias_method :vertical_align, :alignment
20
19
 
21
20
  attr_accessor :bold, :color, :italic, :size, :strike_through, :shadow, :name
22
- alias :font_name :name
23
21
 
24
22
  def initialize(attrs={})
25
23
  self.bold = attrs[:bold] || false
data/lib/xmlss/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Xmlss
2
- VERSION = "1.0.0.rc.1"
2
+ VERSION = "1.0.0.rc.2"
3
3
  end
@@ -101,26 +101,60 @@ module Xmlss
101
101
 
102
102
  # Workbook element attributes API
103
103
 
104
- [ :data, # cell
105
- :type, # cell
106
- :index, # cell
107
- :style_id, # cell, row, :column
108
- :formula, # cell
109
- :href, # cell
110
- :merge_across, # cell
111
- :merge_down, # cell
112
- :height, # row
113
- :auto_fit_height, # row
114
- :hidden, # row, column
115
- :width, # column
116
- :auto_fit_width, # column
117
- :name # worksheet
118
- ].each do |a|
119
- define_method(a) do |value|
120
- if (current_element = self.class.worksheets_stack(self).current)
121
- current_element.send("#{a}=", value)
122
- end
123
- end
104
+ def data(value) # cell
105
+ self.class.worksheets_stack(self).current.data = value
106
+ end
107
+
108
+ def type(value) # cell
109
+ self.class.worksheets_stack(self).current.type = value
110
+ end
111
+
112
+ def index(value) # cell
113
+ self.class.worksheets_stack(self).current.index = value
114
+ end
115
+
116
+ def style_id(value) # cell, row, column
117
+ self.class.worksheets_stack(self).current.style_id = value
118
+ end
119
+
120
+ def formula(value) # cell
121
+ self.class.worksheets_stack(self).current.formula = value
122
+ end
123
+
124
+ def href(value) # cell
125
+ self.class.worksheets_stack(self).current.href = value
126
+ end
127
+
128
+ def merge_across(value) # cell
129
+ self.class.worksheets_stack(self).current.merge_across = value
130
+ end
131
+
132
+ def merge_down(value) # cell
133
+ self.class.worksheets_stack(self).current.merge_down = value
134
+ end
135
+
136
+ def height(value) # row
137
+ self.class.worksheets_stack(self).current.height = value
138
+ end
139
+
140
+ def auto_fit_height(value) # row
141
+ self.class.worksheets_stack(self).current.auto_fit_height = value
142
+ end
143
+
144
+ def hidden(value) # row, column
145
+ self.class.worksheets_stack(self).current.hidden = value
146
+ end
147
+
148
+ def width(value) # column
149
+ self.class.worksheets_stack(self).current.height = value
150
+ end
151
+
152
+ def auto_fit_width(value) # column
153
+ self.class.worksheets_stack(self).current.auto_fit_width = value
154
+ end
155
+
156
+ def name(value) # worksheet
157
+ self.class.worksheets_stack(self).current.name = value
124
158
  end
125
159
 
126
160
  # overriding to make less noisy
data/lib/xmlss/writer.rb CHANGED
@@ -5,6 +5,7 @@ module Xmlss
5
5
  class Writer
6
6
 
7
7
  class Markup; end
8
+ class AttrsHash; end
8
9
 
9
10
  # Xmlss uses Undies to stream its xml markup
10
11
  # The Undies writer is responsible for driving the Undies API to generate
@@ -19,47 +20,14 @@ module Xmlss
19
20
  NS_URI = "urn:schemas-microsoft-com:office:spreadsheet"
20
21
  LB = "&#13;&#10;"
21
22
 
22
- def self.attributes(thing, *attrs)
23
- [*attrs].flatten.inject({}) do |xattrs, a|
24
- xattrs.merge(if !(xv = self.coerce(thing.send(a))).nil?
25
- {xmlss_attribute_name(a) => xv.to_s}
26
- else
27
- {}
28
- end)
29
- end
30
- end
31
-
32
- def self.xmlss_attribute_name(attr_name)
33
- "#{SHEET_NS}:#{self.classify(attr_name)}"
34
- end
35
-
36
- def self.classify(underscored_string)
37
- underscored_string.
38
- to_s.downcase.
39
- split("_").
40
- collect{|part| part.capitalize}.
41
- join('')
42
- end
43
-
44
- def self.coerce(value)
45
- if value == true
46
- 1
47
- elsif ["",false].include?(value)
48
- # don't include false or empty string values
49
- nil
50
- else
51
- value
52
- end
53
- end
54
-
55
23
  attr_reader :styles_markup
56
24
  attr_reader :worksheets_markup
57
25
 
58
26
  def initialize(output_opts={})
59
27
  @opts = output_opts || {}
60
28
 
61
- @styles_markup = Markup.new(@opts.merge(:pp_level => 2))
62
- @worksheets_markup = Markup.new(@opts.merge(:pp_level => 1))
29
+ @styles_markup = Markup.new(@opts.merge(:level => 2))
30
+ @worksheets_markup = Markup.new(@opts.merge(:level => 1))
63
31
  end
64
32
 
65
33
  def write(element)
@@ -87,103 +55,128 @@ module Xmlss
87
55
  self.flush
88
56
  "".tap do |markup|
89
57
  Undies::Template.new(Undies::Source.new(Proc.new do
90
- __ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
91
- _Workbook(XML_NS => NS_URI, "#{XML_NS}:#{SHEET_NS}" => NS_URI) {
92
- _Styles {
93
- __partial styles
58
+ _ raw("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
59
+ __open_element("Workbook", XML_NS => NS_URI, "#{XML_NS}:#{SHEET_NS}" => NS_URI) {
60
+ __open_element("Styles") {
61
+ __partial @styles
94
62
  }
95
- __partial worksheets
63
+ __partial @worksheets
96
64
  }
97
65
  end), {
98
66
  :styles => styles_markup.to_s,
99
67
  :worksheets => worksheets_markup.to_s
100
- }, Undies::Output.new(StringIO.new(markup), @opts))
68
+ }, Undies::IO.new(markup, @opts))
101
69
  end.strip
102
70
  end
103
71
 
104
72
  # workbook style markup directives
105
73
 
106
74
  def alignment(alignment)
107
- styles_markup.template._Alignment(self.class.attributes(alignment, [
108
- :horizontal, :vertical, :wrap_text, :rotate
109
- ]))
75
+ styles_markup.inline_element("Alignment", AttrsHash.new.
76
+ value("Horizontal", alignment.horizontal).
77
+ value("Vertical", alignment.vertical).
78
+ value("Rotate", alignment.rotate).
79
+ bool( "WrapText", alignment.wrap_text).
80
+ raw
81
+ )
110
82
  end
111
83
 
112
84
  def border(border)
113
- styles_markup.template._Border(self.class.attributes(border, [
114
- :color, :position, :weight, :line_style
115
- ]))
85
+ styles_markup.inline_element("Border", AttrsHash.new.
86
+ value("Color", border.color).
87
+ value("Position", border.position).
88
+ value("Weight", border.weight).
89
+ value("LineStyle", border.line_style).
90
+ raw
91
+ )
116
92
  end
117
93
 
118
94
  def borders(borders)
119
- styles_markup.template._Borders
95
+ styles_markup.element("Borders", nil, {})
120
96
  end
121
97
 
122
98
  def font(font)
123
- styles_markup.template._Font(self.class.attributes(font, [
124
- :bold, :color, :italic, :size, :shadow, :font_name,
125
- :strike_through, :underline, :vertical_align
126
- ]))
99
+ styles_markup.inline_element("Font", AttrsHash.new.
100
+ bool( "Bold", font.bold).
101
+ value("Color", font.color).
102
+ bool( "Italic", font.italic).
103
+ value("Size", font.size).
104
+ bool( "Shadow", font.shadow).
105
+ value("FontName", font.name).
106
+ bool( "StrikeThrough", font.strike_through).
107
+ value("Underline", font.underline).
108
+ value("VerticalAlign", font.alignment).
109
+ raw
110
+ )
127
111
  end
128
112
 
129
113
  def interior(interior)
130
- styles_markup.template._Interior(self.class.attributes(interior, [
131
- :color, :pattern, :pattern_color
132
- ]))
114
+ styles_markup.inline_element("Interior", AttrsHash.new.
115
+ value("Color", interior.color).
116
+ value("Pattern", interior.pattern).
117
+ value("PatternColor", interior.pattern_color).
118
+ raw
119
+ )
133
120
  end
134
121
 
135
122
  def number_format(number_format)
136
- styles_markup.template._NumberFormat(self.class.attributes(number_format, [
137
- :format
138
- ]))
123
+ a = AttrsHash.new.value("Format", number_format.format).raw
124
+ styles_markup.inline_element("NumberFormat", a)
139
125
  end
140
126
 
141
127
  def protection(protection)
142
- styles_markup.template._Protection(self.class.attributes(protection, [
143
- :protect
144
- ]))
128
+ a = AttrsHash.new.bool("Protect", protection.protect).raw
129
+ styles_markup.inline_element("Protection", a)
145
130
  end
146
131
 
147
132
  def style(style)
148
- styles_markup.template._Style(self.class.attributes(style, [
149
- :i_d
150
- ]))
133
+ a = AttrsHash.new.value("ID", style.id).raw
134
+ styles_markup.element("Style", nil, a)
151
135
  end
152
136
 
153
137
  # workbook element markup directives
154
138
 
155
139
  def cell(cell)
156
140
  # write the cell markup and push
157
- worksheets_markup.template._Cell(self.class.attributes(cell, [
158
- [:index, :style_i_d, :formula, :h_ref, :merge_across, :merge_down]
159
- ]))
141
+ worksheets_markup.element("Cell", nil, AttrsHash.new.
142
+ value("Index", cell.index).
143
+ value("StyleID", cell.style_id).
144
+ value("Formula", cell.formula).
145
+ value("HRef", cell.href).
146
+ value("MergeAcross", cell.merge_across).
147
+ value("MergeDown", cell.merge_down).
148
+ raw
149
+ )
160
150
  push(:worksheets)
161
151
 
162
152
  # write nested data markup and push
163
- worksheets_markup.template._Data(self.class.attributes(cell, [
164
- [:type]
165
- ]))
166
- push(:worksheets)
167
-
168
- # write data value
169
- worksheets_markup.template.__ Undies::Template.
170
- escape_html(cell.data_xml_value).
171
- gsub(/(\r|\n)+/, LB)
153
+ worksheets_markup.element(
154
+ "Data",
155
+ worksheets_markup.raw(cell.data_xml_value),
156
+ AttrsHash.new.value("Type", cell.type).raw
157
+ )
172
158
 
173
159
  pop(:worksheets)
174
- pop(:worksheets)
175
160
  end
176
161
 
177
162
  def row(row)
178
- worksheets_markup.template._Row(self.class.attributes(row, [
179
- [:style_i_d, :height, :auto_fit_height, :hidden]
180
- ]))
163
+ worksheets_markup.element("Row", nil, AttrsHash.new.
164
+ value("StyleID", row.style_id).
165
+ value("Height", row.height).
166
+ bool( "AutoFitHeight", row.auto_fit_height).
167
+ bool( "Hidden", row.hidden).
168
+ raw
169
+ )
181
170
  end
182
171
 
183
172
  def column(column)
184
- worksheets_markup.template._Column(self.class.attributes(column, [
185
- [:style_i_d, :width, :auto_fit_width, :hidden]
186
- ]))
173
+ worksheets_markup.inline_element("Column", AttrsHash.new.
174
+ value("StyleID", column.style_id).
175
+ value("Width", column.width).
176
+ bool( "AutoFitWidth", column.auto_fit_width).
177
+ bool( "Hidden", column.hidden).
178
+ raw
179
+ )
187
180
  end
188
181
 
189
182
  def worksheet(worksheet)
@@ -191,30 +184,65 @@ module Xmlss
191
184
  worksheets_markup.flush
192
185
 
193
186
  # write the worksheet markup and push
194
- worksheets_markup.template._Worksheet(self.class.attributes(worksheet, [
195
- [:name]
196
- ]))
187
+ a = AttrsHash.new.value("Name", worksheet.name).raw
188
+ worksheets_markup.element("Worksheet", nil, a)
197
189
  push(:worksheets)
198
190
 
199
191
  # write the table container
200
- worksheets_markup.template._Table
192
+ worksheets_markup.element("Table", nil, {})
201
193
  end
202
194
 
203
195
  end
204
196
 
205
197
 
206
198
 
199
+ class Writer::AttrsHash
200
+
201
+ attr_reader :raw
202
+
203
+ def initialize
204
+ @raw = Hash.new
205
+ end
206
+
207
+ def value(k, v)
208
+ # ignore any nil-value or empty string attrs
209
+ @raw["#{Xmlss::Writer::SHEET_NS}:#{k}"] = v if v && v != ''
210
+ self
211
+ end
212
+
213
+ def bool(k, v)
214
+ # write truthy values as '1', otherwise ignore
215
+ @raw["#{Xmlss::Writer::SHEET_NS}:#{k}"] = 1 if v
216
+ self
217
+ end
218
+
219
+ end
220
+
207
221
  class Writer::Markup
208
222
 
209
223
  attr_reader :template, :push_count, :pop_count
210
224
 
211
225
  def initialize(opts={})
212
226
  @markup = ""
213
- @template = Undies::Template.new(Undies::Output.new(StringIO.new(@markup), opts))
227
+ @template = Undies::Template.new(Undies::IO.new(@markup, opts))
214
228
  @push_count = 0
215
229
  @pop_count = 0
216
230
  end
217
231
 
232
+ def raw(markup)
233
+ @template.raw(
234
+ Undies::Template.escape_html(markup).gsub(/(\r|\n)+/, Xmlss::Writer::LB)
235
+ )
236
+ end
237
+
238
+ def element(name, data, attrs)
239
+ @template.__open_element(name, data, attrs)
240
+ end
241
+
242
+ def inline_element(name, attrs)
243
+ @template.__closed_element(name, attrs)
244
+ end
245
+
218
246
  def push
219
247
  @push_count += 1
220
248
  @template.__push
@@ -236,7 +264,7 @@ module Xmlss
236
264
  def empty?; @markup.empty?; end
237
265
 
238
266
  def to_s
239
- @markup.to_s.strip
267
+ @markup.to_s
240
268
  end
241
269
 
242
270
  end
@@ -15,7 +15,6 @@ module Xmlss::Element
15
15
  should be_styled
16
16
  should have_class_method :writer
17
17
  should have_accessor :index, :formula, :href, :merge_across, :merge_down
18
- should have_reader :h_ref
19
18
 
20
19
  should have_enum :type, {
21
20
  :number => "Number",
@@ -42,12 +41,6 @@ module Xmlss::Element
42
41
  assert_equal "", subject.data
43
42
  end
44
43
 
45
- should "provide alias for :href" do
46
- c = Cell.new({:href => "http://www.google.com"})
47
- assert_equal "http://www.google.com", c.href
48
- assert_equal "http://www.google.com", c.h_ref
49
- end
50
-
51
44
  should "bark when setting non Fixnum indices" do
52
45
  assert_raises ArgumentError do
53
46
  Cell.new({:index => "do it"})
data/test/helper.rb CHANGED
@@ -6,26 +6,15 @@ $LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
6
6
 
7
7
  class Assert::Context
8
8
 
9
- class << self
9
+ def self.be_styled
10
+ called_from = caller.first
11
+ Assert::Macro.new("have style attributes") do
12
+ should have_accessor :style_id
10
13
 
11
- def be_styled
12
- called_from = caller.first
13
- Assert::Macro.new("have style attributes") do
14
- should have_accessor :style_id
15
- should have_reader :style_i_d
16
-
17
- should "set the style default" do
18
- assert_equal nil, subject.class.new.style_id
19
- end
20
-
21
- should "provide aliases for style_id" do
22
- c = subject.class.new({:style_id => :poo})
23
- assert_equal :poo, c.style_id
24
- assert_equal :poo, c.style_i_d
25
- end
14
+ should "set the style default" do
15
+ assert_equal nil, subject.class.new.style_id
26
16
  end
27
17
  end
28
-
29
18
  end
30
19
 
31
20
  end
@@ -9,7 +9,7 @@ module Xmlss::Style
9
9
  subject { @bs }
10
10
 
11
11
  should have_class_method :writer
12
- should have_reader :id, :i_d
12
+ should have_reader :id
13
13
 
14
14
  should "know its writer" do
15
15
  assert_equal :style, subject.class.writer
@@ -24,7 +24,6 @@ module Xmlss::Style
24
24
  }
25
25
 
26
26
  should have_class_method :writer
27
- should have_reader :vertical_align
28
27
  should have_accessors :bold, :color, :italic, :size, :strike_through
29
28
  should have_accessors :shadow, :underline, :alignment, :name
30
29
  should have_instance_methods :bold?, :italic?, :strike_through?, :shadow?
@@ -39,13 +39,6 @@ module Xmlss::Worbook
39
39
  assert_kind_of Xmlss::Style::Protection, subject.protection
40
40
  end
41
41
 
42
- should "not complain if setting an attribute when there's no current element" do
43
- # it should just do nothing and go on
44
- assert_nothing_raised do
45
- subject.index(1)
46
- end
47
- end
48
-
49
42
  should "return workbook markup string" do
50
43
  assert_match /<Workbook /, subject.to_s
51
44
  end
@@ -83,7 +76,7 @@ module Xmlss::Worbook
83
76
  end
84
77
 
85
78
  assert_equal(
86
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"><Styles><Style ss:ID=\"test\"><Alignment /><Borders><Border ss:LineStyle=\"Continuous\" ss:Weight=\"1\" /></Borders><Font /><Interior /><NumberFormat /><Protection /></Style></Styles><Worksheet ss:Name=\"test\"><Table><Column /><Row><Cell><Data ss:Type=\"Number\">#{wkbk.object_id}</Data></Cell></Row></Table></Worksheet></Workbook>",
79
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"><Styles><Style ss:ID=\"test\"><Alignment /><Borders><Border ss:LineStyle=\"Continuous\" ss:Weight=\"1\" /></Borders><Font /><Interior /><NumberFormat /><Protection /></Style></Styles><Worksheet ss:Name=\"test\"><Table><Column /><Row><Cell><Data ss:Type=\"Number\">#{wkbk.object_id}</Data></Cell></Row></Table></Worksheet></Workbook>",
87
80
  wkbk.to_s
88
81
  )
89
82
  end
@@ -118,7 +111,7 @@ module Xmlss::Worbook
118
111
  worksheet worksheet_name
119
112
  end
120
113
  assert_equal(
121
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"><Styles></Styles><Worksheet ss:Name=\"awesome\"><Table /></Worksheet></Workbook>",
114
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"><Styles></Styles><Worksheet ss:Name=\"awesome\"><Table></Table></Worksheet></Workbook>",
122
115
  wkbk.to_s
123
116
  )
124
117
  end
data/test/writer_test.rb CHANGED
@@ -14,7 +14,6 @@ module Xmlss
14
14
  end
15
15
  subject { @w }
16
16
 
17
- should have_class_methods :attributes, :classify, :coerce
18
17
  should have_readers :styles_markup, :worksheets_markup
19
18
  should have_instance_methods :write, :push, :pop, :flush, :workbook
20
19
 
@@ -36,44 +35,35 @@ module Xmlss
36
35
 
37
36
 
38
37
 
39
- class HelpersTests < BasicTests
38
+ class AttrsHashTests < BasicTests
39
+ desc "AttrsHash"
40
+ before do
41
+ @a = Writer::AttrsHash.new
42
+ end
43
+ subject { @a }
44
+
45
+ should have_reader :raw
46
+ should have_instance_methods :value, :bool
47
+
48
+ should "by default have an empty raw hash" do
49
+ assert_equal({}, subject.raw)
50
+ end
51
+
52
+ should "apply values to a raw hash with the writer namespace" do
53
+ assert_equal({"#{Writer::SHEET_NS}:a" => 'b'}, subject.value('a', 'b').raw)
54
+ end
40
55
 
41
- should "coerce certain values for xml output" do
42
- assert_equal 1, Writer.coerce(true)
43
- assert_nil Writer.coerce(false)
44
- assert_nil Writer.coerce("")
45
- assert_equal "hi", Writer.coerce("hi")
46
- assert_equal 1, Writer.coerce(1)
56
+ should "ignore nil values" do
57
+ assert_equal({}, subject.value('a', nil).raw)
47
58
  end
48
59
 
49
- should "classify underscored string" do
50
- assert_equal "Hi", Writer.classify("Hi")
51
- assert_equal "Hi", Writer.classify("hi")
52
- assert_equal "Hithere", Writer.classify("HiThere")
53
- assert_equal "Hithere", Writer.classify("hithere")
54
- assert_equal "HiThere", Writer.classify("Hi_There")
55
- assert_equal "HiThere", Writer.classify("Hi_there")
56
- assert_equal "HiThere", Writer.classify("hi_there")
60
+ should "ignore empty string values" do
61
+ assert_equal({}, subject.value('a', '').raw)
57
62
  end
58
63
 
59
- should "convert a list of attributes for xml output" do
60
- class Thing
61
- def keys; [:thing, :other, 'some', 'hi', :hi_there]; end
62
-
63
- def thing; true; end
64
- def other; false; end
65
- def some; ""; end
66
- def hi; :there; end
67
- def hi_there; "you"; end
68
- end
69
- thing = Thing.new
70
- exp = {
71
- "ss:Hi" => "there",
72
- "ss:HiThere" => "you",
73
- "ss:Thing" => "1"
74
- }
75
-
76
- assert_equal exp, Writer.attributes(thing, thing.keys)
64
+ should "apply booleans as '1' and otherwise ignore" do
65
+ assert_equal({}, subject.bool('a', false).raw)
66
+ assert_equal({"#{Writer::SHEET_NS}:a" => 1}, subject.bool('a', true).raw)
77
67
  end
78
68
 
79
69
  end
@@ -392,7 +382,7 @@ Should
392
382
  should "return workbook markup" do
393
383
  build_workbook(subject)
394
384
  assert_equal(
395
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"><Styles><Style ss:ID=\"some_font\"><Font ss:Bold=\"1\" /></Style><Style ss:ID=\"some_numformat\"><NumberFormat ss:Format=\"General\" /></Style></Styles><Worksheet ss:Name=\"test1\"><Table><Row ss:Hidden=\"1\"><Cell ss:Index=\"2\"><Data ss:Type=\"String\">some data</Data></Cell></Row></Table></Worksheet><Worksheet ss:Name=\"test2\"><Table><Row ss:Hidden=\"1\"><Cell ss:Index=\"2\"><Data ss:Type=\"String\">some data</Data></Cell></Row></Table></Worksheet></Workbook>",
385
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"><Styles><Style ss:ID=\"some_font\"><Font ss:Bold=\"1\" /></Style><Style ss:ID=\"some_numformat\"><NumberFormat ss:Format=\"General\" /></Style></Styles><Worksheet ss:Name=\"test1\"><Table><Row ss:Hidden=\"1\"><Cell ss:Index=\"2\"><Data ss:Type=\"String\">some data</Data></Cell></Row></Table></Worksheet><Worksheet ss:Name=\"test2\"><Table><Row ss:Hidden=\"1\"><Cell ss:Index=\"2\"><Data ss:Type=\"String\">some data</Data></Cell></Row></Table></Worksheet></Workbook>",
396
386
  subject.workbook
397
387
  )
398
388
  end
data/xmlss.gemspec CHANGED
@@ -17,8 +17,8 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_development_dependency("bundler", ["~> 1.0"])
21
- s.add_development_dependency("assert", ["~> 0.6"])
22
- s.add_dependency("undies", ["~> 2.2.1"])
20
+ s.add_development_dependency("assert", ["~> 0.7.3"])
21
+ s.add_development_dependency("assert-view", ["~> 0.6"])
22
+ s.add_dependency("undies", ["~> 3.0.0.rc.1"])
23
23
  s.add_dependency("enumeration", ["~> 1.3"])
24
24
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xmlss
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15424055
4
+ hash: 15424049
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
9
  - 0
10
10
  - rc
11
- - 1
12
- version: 1.0.0.rc.1
11
+ - 2
12
+ version: 1.0.0.rc.2
13
13
  platform: ruby
14
14
  authors:
15
15
  - Kelly Redding
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2012-03-15 00:00:00 Z
20
+ date: 2012-04-17 00:00:00 Z
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
23
  type: :development
@@ -26,12 +26,13 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- hash: 15
29
+ hash: 5
30
30
  segments:
31
- - 1
32
31
  - 0
33
- version: "1.0"
34
- name: bundler
32
+ - 7
33
+ - 3
34
+ version: 0.7.3
35
+ name: assert
35
36
  version_requirements: *id001
36
37
  prerelease: false
37
38
  - !ruby/object:Gem::Dependency
@@ -46,7 +47,7 @@ dependencies:
46
47
  - 0
47
48
  - 6
48
49
  version: "0.6"
49
- name: assert
50
+ name: assert-view
50
51
  version_requirements: *id002
51
52
  prerelease: false
52
53
  - !ruby/object:Gem::Dependency
@@ -56,12 +57,14 @@ dependencies:
56
57
  requirements:
57
58
  - - ~>
58
59
  - !ruby/object:Gem::Version
59
- hash: 5
60
+ hash: 15424119
60
61
  segments:
61
- - 2
62
- - 2
62
+ - 3
63
+ - 0
64
+ - 0
65
+ - rc
63
66
  - 1
64
- version: 2.2.1
67
+ version: 3.0.0.rc.1
65
68
  name: undies
66
69
  version_requirements: *id003
67
70
  prerelease: false
@@ -95,6 +98,7 @@ files:
95
98
  - Gemfile.lock
96
99
  - README.rdoc
97
100
  - Rakefile
101
+ - bench/bench_runner.rb
98
102
  - bench/profiler.rb
99
103
  - bench/profiler_runner.rb
100
104
  - examples/example_workbook.rb