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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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