math_ml 0.9
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/Rakefile +49 -0
- data/Rakefile.utirake +334 -0
- data/lib/math_ml/element.rb +227 -0
- data/lib/math_ml/latex/builtin_commands.rb +547 -0
- data/lib/math_ml/latex.rb +1097 -0
- data/lib/math_ml/string.rb +32 -0
- data/lib/math_ml/util.rb +350 -0
- data/lib/math_ml.rb +25 -0
- data/spec/math_ml_element_spec.rb +32 -0
- data/spec/math_ml_latex_macro_spec.rb +122 -0
- data/spec/math_ml_latex_parser_spec.rb +479 -0
- data/spec/math_ml_latex_scanner_spec.rb +202 -0
- data/spec/math_ml_spec.rb +14 -0
- data/spec/math_ml_string_spec.rb +29 -0
- data/spec/math_ml_util_spec.rb +700 -0
- data/spec/util.rb +32 -0
- metadata +96 -0
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
load "Rakefile.utirake"
|
2
|
+
|
3
|
+
VER = "0.9"
|
4
|
+
|
5
|
+
UtiRake.setup do
|
6
|
+
external("https://hg.hinet.mydns.jp", %w[eim_xml])
|
7
|
+
|
8
|
+
rdoc do |t|
|
9
|
+
t.title = "MathML Library"
|
10
|
+
t.main = "README"
|
11
|
+
t.rdoc_files << FileList["lib/**/*.rb", "README"]
|
12
|
+
end
|
13
|
+
|
14
|
+
publish("mathml", "hiraku") do
|
15
|
+
cp "index.html", "html/index.html"
|
16
|
+
end
|
17
|
+
|
18
|
+
gemspec do |s|
|
19
|
+
s.name = "math_ml"
|
20
|
+
s.rubyforge_project = "mathml"
|
21
|
+
s.version = VER
|
22
|
+
s.summary = "MathML Library"
|
23
|
+
s.author = "KURODA Hiraku"
|
24
|
+
s.email = "hiraku@hinet.mydns.jp"
|
25
|
+
s.homepage = "http://mathml.rubyforge.org/"
|
26
|
+
s.add_dependency("eim_xml")
|
27
|
+
end
|
28
|
+
|
29
|
+
rcov_spec do |s|
|
30
|
+
s.spec_files << FileList["symbols/**/*_spec.rb"]
|
31
|
+
end
|
32
|
+
|
33
|
+
spec do |s|
|
34
|
+
# s.spec_opts << "-b"
|
35
|
+
end
|
36
|
+
alias_task
|
37
|
+
end
|
38
|
+
|
39
|
+
namespace :spec do
|
40
|
+
Spec::Rake::SpecTask.new(:symbols) do |s|
|
41
|
+
s.spec_files = FileList["./symbols/**/*_spec.rb"]
|
42
|
+
s.spec_opts << "-c"
|
43
|
+
s.libs << "lib" << "external/lib"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
task :default => :spec
|
48
|
+
task "spec:no_here" => "spec:apart"
|
49
|
+
task :all => [:spec, "spec:symbols"]
|
data/Rakefile.utirake
ADDED
@@ -0,0 +1,334 @@
|
|
1
|
+
# Utility for Rake
|
2
|
+
#
|
3
|
+
# Copyright (C) 2008, KURODA Hiraku <hiraku@hinet.mydns.jp>
|
4
|
+
# You can redistribute it and/or modify it under GPL3.
|
5
|
+
|
6
|
+
require "rake/clean"
|
7
|
+
require "rake/testtask"
|
8
|
+
require "rake/rdoctask"
|
9
|
+
require "rake/gempackagetask"
|
10
|
+
require "rake/contrib/rubyforgepublisher"
|
11
|
+
require "rubygems/package_task"
|
12
|
+
|
13
|
+
class UtiRake
|
14
|
+
def self.setup(opt={}, &proc)
|
15
|
+
ur = new
|
16
|
+
ur.setup(opt, &proc)
|
17
|
+
rescue
|
18
|
+
puts $!.class, $!.message, $!.backtrace
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :opt, :spec_proc, :cucumber_proc, :rdoc_proc, :gemspec_proc, :package_proc, :rcov_spec_proc
|
22
|
+
|
23
|
+
def setup(opt={}, &proc)
|
24
|
+
@opt = opt
|
25
|
+
directory "external"
|
26
|
+
CLOBBER << "external" << "coverage" << "coverage.spec" << "coverage.cuke" << "doc"
|
27
|
+
|
28
|
+
instance_eval(&proc) if proc
|
29
|
+
|
30
|
+
if need_spec?
|
31
|
+
require "spec/rake/spectask"
|
32
|
+
define_spec_task
|
33
|
+
end
|
34
|
+
|
35
|
+
if need_cucumber?
|
36
|
+
require "cucumber/rake/task"
|
37
|
+
define_cucumber_task
|
38
|
+
end
|
39
|
+
|
40
|
+
define_rdoc_task
|
41
|
+
define_rcov_task
|
42
|
+
define_package_task
|
43
|
+
define_here_dependency
|
44
|
+
define_alias_task if @alias_task
|
45
|
+
end
|
46
|
+
|
47
|
+
def need_spec?
|
48
|
+
File.directory?("spec")
|
49
|
+
end
|
50
|
+
|
51
|
+
def need_cucumber?
|
52
|
+
File.directory?("features")
|
53
|
+
end
|
54
|
+
|
55
|
+
def spec(&proc)
|
56
|
+
@spec_proc = proc
|
57
|
+
end
|
58
|
+
|
59
|
+
def cucumber(&proc)
|
60
|
+
@cucumber_proc = proc
|
61
|
+
end
|
62
|
+
|
63
|
+
def rdoc(&proc)
|
64
|
+
@rdoc_proc = proc
|
65
|
+
end
|
66
|
+
|
67
|
+
def gemspec(&proc)
|
68
|
+
@gemspec_proc = proc
|
69
|
+
end
|
70
|
+
|
71
|
+
def rcov_spec(&proc)
|
72
|
+
@rcov_spec_proc = proc
|
73
|
+
end
|
74
|
+
|
75
|
+
def package(&proc)
|
76
|
+
@package_proc = proc
|
77
|
+
end
|
78
|
+
|
79
|
+
def no_here(task)
|
80
|
+
@no_here_task = task
|
81
|
+
end
|
82
|
+
|
83
|
+
def no_here_task
|
84
|
+
@no_here_task || "spec:lump"
|
85
|
+
end
|
86
|
+
|
87
|
+
def alias_task
|
88
|
+
@alias_task = true
|
89
|
+
end
|
90
|
+
|
91
|
+
def hg(cmd)
|
92
|
+
sh "hg #{cmd.to_s}"
|
93
|
+
end
|
94
|
+
|
95
|
+
def external(base_url, *libs)
|
96
|
+
libs = libs.first if libs.first.is_a?(Array)
|
97
|
+
namespace :external do
|
98
|
+
directory "external/lib"
|
99
|
+
libs.each do |lib|
|
100
|
+
libdir = "external/#{lib}"
|
101
|
+
file libdir => "external/lib" do
|
102
|
+
if File.exist?("../#{lib}")
|
103
|
+
Dir.chdir("external") do
|
104
|
+
ln_s "../../#{lib}", "./", :force=>true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
hg "clone #{File.join(base_url, lib)} #{libdir}" unless File.exist?(libdir)
|
108
|
+
Dir["#{libdir}/lib/*"].each do |f|
|
109
|
+
base = File.basename(f)
|
110
|
+
cd "external/lib" do
|
111
|
+
ln_s "../#{lib}/lib/#{base}", "./"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
if File.exist?(libdir)
|
117
|
+
Dir["#{libdir}/lib/*"].each do |f|
|
118
|
+
base = File.basename(f)
|
119
|
+
file "external/lib/#{base}" => "external/lib" do
|
120
|
+
cd "external/lib" do
|
121
|
+
ln_s "../#{lib}/lib/#{base}", "./"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
task :setup => "external/lib/#{base}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
desc "Setup external libraries"
|
129
|
+
task :setup=>libdir
|
130
|
+
end
|
131
|
+
|
132
|
+
task :rake => :setup do
|
133
|
+
libs.each do |lib|
|
134
|
+
Dir.chdir "external/#{lib}" do
|
135
|
+
sh "rake"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
@external = true
|
141
|
+
end
|
142
|
+
|
143
|
+
def external?; @external; end
|
144
|
+
|
145
|
+
def define_rdoc_task
|
146
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
147
|
+
rdoc.options << "-S"
|
148
|
+
rdoc.options << "-w" << "3"
|
149
|
+
rdoc.options << "-c" << "UTF-8"
|
150
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
151
|
+
rdoc_proc.call(rdoc) if rdoc_proc
|
152
|
+
end
|
153
|
+
task :doc do
|
154
|
+
remove_entry_secure "doc" if File.directory?("doc")
|
155
|
+
sh "rdoc -S -w 3 -c UTF-8 -d -x external"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def define_package_task
|
160
|
+
spec = Gem::Specification.new do |s|
|
161
|
+
s.platform = Gem::Platform::RUBY
|
162
|
+
s.files = FileList["Rakefile*", "lib/**/*", "spec/**/*"]
|
163
|
+
s.version = ENV["VER"] || "0.0.0.noversion"
|
164
|
+
gemspec_proc.call(s) if gemspec_proc
|
165
|
+
end
|
166
|
+
|
167
|
+
gem = Gem::PackageTask.new(spec) do |t|
|
168
|
+
t.need_tar_gz = true
|
169
|
+
t.need_zip = true
|
170
|
+
package_proc.call(t) if package_proc
|
171
|
+
end
|
172
|
+
|
173
|
+
task "utirake:gem" do
|
174
|
+
mv "Rakefile.utirake", "Rakefile.utirake_#{$$}"
|
175
|
+
symlink "external/utirake/utirake.rb", "Rakefile.utirake"
|
176
|
+
end
|
177
|
+
|
178
|
+
file "#{gem.package_dir}/#{gem.gem_spec.file_name}" => "utirake:gem"
|
179
|
+
|
180
|
+
task :gem do
|
181
|
+
rm "Rakefile.utirake"
|
182
|
+
mv "Rakefile.utirake_#{$$}", "Rakefile.utirake"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def publish(project_name, user_id)
|
187
|
+
task :publish => "rdoc" do
|
188
|
+
yield if block_given
|
189
|
+
Rake::RubyForgePublisher.new(project_name, user_id).upload
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
FILE_SORT = lambda{|a, b| File.mtime(a)<=>File.mtime(b)}
|
194
|
+
|
195
|
+
def spec_files
|
196
|
+
@spec_files ||= FileList["./spec/**/*_spec.rb"].sort(&FILE_SORT).reverse
|
197
|
+
end
|
198
|
+
|
199
|
+
def set_spec_opts(spec)
|
200
|
+
spec.spec_opts << "-c"
|
201
|
+
spec.libs << "." << "./lib" << "./external/lib"
|
202
|
+
end
|
203
|
+
|
204
|
+
def define_spec_task
|
205
|
+
task :spec => "spec:apart"
|
206
|
+
namespace :spec do
|
207
|
+
spec_files.each do |f|
|
208
|
+
desc ""
|
209
|
+
Spec::Rake::SpecTask.new(:apart) do |s|
|
210
|
+
s.spec_files = FileList[f]
|
211
|
+
set_spec_opts(s)
|
212
|
+
spec_proc.call(s) if spec_proc
|
213
|
+
end
|
214
|
+
end
|
215
|
+
task(:apart).comment = "Run all specs separately"
|
216
|
+
|
217
|
+
desc "Run all specs in a lump"
|
218
|
+
Spec::Rake::SpecTask.new(:lump) do |s|
|
219
|
+
s.spec_files = spec_files
|
220
|
+
set_spec_opts(s)
|
221
|
+
spec_proc.call(s) if spec_proc
|
222
|
+
end
|
223
|
+
|
224
|
+
desc "Run all specs to profile"
|
225
|
+
Spec::Rake::SpecTask.new(:profile) do |s|
|
226
|
+
set_spec_opts(s)
|
227
|
+
s.spec_opts << "-f" << "profile"
|
228
|
+
end
|
229
|
+
|
230
|
+
`grep -sRn '#[[:space:]]*here[[:space:]]*$' spec`.split(/\n/).map{|l|
|
231
|
+
next nil unless l=~/\A(.*?):(\d+):/
|
232
|
+
[$1, $2.to_i]
|
233
|
+
}.compact.sort{|a, b| FILE_SORT.call(a[0], b[0])}.reverse.each do |file, line|
|
234
|
+
desc ""
|
235
|
+
Spec::Rake::SpecTask.new(:here) do |s|
|
236
|
+
s.spec_files = [file]
|
237
|
+
set_spec_opts(s)
|
238
|
+
s.spec_opts << "-l#{line}"
|
239
|
+
spec_proc.call(s) if spec_proc
|
240
|
+
end
|
241
|
+
end
|
242
|
+
task :no_here => no_here_task
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def set_cucumber_opts(task)
|
247
|
+
task.libs << "."
|
248
|
+
cucumber_proc.call(task) if cucumber_proc
|
249
|
+
end
|
250
|
+
|
251
|
+
def define_cucumber_task
|
252
|
+
Cucumber::Rake::Task.new do |t|
|
253
|
+
set_cucumber_opts(t)
|
254
|
+
end
|
255
|
+
|
256
|
+
unless `grep -sRn '^[[:space:]]*@here$' features`.empty?
|
257
|
+
Cucumber::Rake::Task.new("cucumber:here") do |t|
|
258
|
+
t.cucumber_opts = %w[--tags @here]
|
259
|
+
set_cucumber_opts(t)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
task "cucumber:no_here" => :cucumber
|
263
|
+
end
|
264
|
+
|
265
|
+
def define_here_dependency
|
266
|
+
unless Rake::Task.task_defined?("spec:here") || Rake::Task.task_defined?("cucumber:here")
|
267
|
+
task "spec:here" => "spec:no_here" if need_spec? && !Rake::Task.task_defined?("spec:here")
|
268
|
+
task "cucumber:here" => "cucumber:no_here" if need_cucumber? && !Rake::Task.task_defined?("cucumber:here")
|
269
|
+
end
|
270
|
+
|
271
|
+
task("spec:here").comment = "Run spec only marked '# here'"
|
272
|
+
task("cucumber:here").comment = "only tagged '@here'"
|
273
|
+
end
|
274
|
+
|
275
|
+
def rcov_opts(t, aggregation)
|
276
|
+
t.rcov_opts << "--exclude" << "gems\/,features\/,external\/"
|
277
|
+
t.rcov_opts << "--aggregate" << "coverage.data" if aggregation
|
278
|
+
t.rcov = true
|
279
|
+
end
|
280
|
+
|
281
|
+
def define_rcov_each_task(aggregation)
|
282
|
+
if need_spec?
|
283
|
+
Spec::Rake::SpecTask.new do |t|
|
284
|
+
t.spec_files = spec_files
|
285
|
+
rcov_opts(t, aggregation)
|
286
|
+
set_spec_opts(t)
|
287
|
+
rcov_spec_proc.call(t) if rcov_spec_proc
|
288
|
+
t.rcov_dir = "coverage.spec" unless aggregation
|
289
|
+
end
|
290
|
+
else
|
291
|
+
task "spec"
|
292
|
+
end
|
293
|
+
|
294
|
+
if need_cucumber?
|
295
|
+
Cucumber::Rake::Task.new do |t|
|
296
|
+
set_cucumber_opts(t)
|
297
|
+
rcov_opts(t, aggregation)
|
298
|
+
t.rcov_opts << "-o" << "coverage.cuke" unless aggregation
|
299
|
+
end
|
300
|
+
else
|
301
|
+
task "cucumber"
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def define_rcov_task
|
306
|
+
namespace :rcov do
|
307
|
+
define_rcov_each_task(false)
|
308
|
+
end
|
309
|
+
|
310
|
+
desc "Run specs and Cucumber using RCov"
|
311
|
+
task "rcov:lump" do
|
312
|
+
rm "coverage.data" if File.exist?("coverage.data")
|
313
|
+
ns = namespace do
|
314
|
+
define_rcov_each_task(true)
|
315
|
+
end
|
316
|
+
ns.tasks.each do |t|
|
317
|
+
t.invoke
|
318
|
+
end
|
319
|
+
rm "coverage.data"
|
320
|
+
end
|
321
|
+
|
322
|
+
task "rcov:all" => %w[rcov:spec rcov:cucumber rcov:lump]
|
323
|
+
end
|
324
|
+
|
325
|
+
def define_alias_task
|
326
|
+
if Rake::Task.task_defined?("spec:apart")
|
327
|
+
task :apart => "spec:apart"
|
328
|
+
task :lump => "spec:lump"
|
329
|
+
task :here => "spec:here"
|
330
|
+
task :profile => "spec:profile"
|
331
|
+
end
|
332
|
+
task :here => "cucumber:here" if Rake::Task.task_defined?("cucumber:here")
|
333
|
+
end
|
334
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
module MathML
|
2
|
+
class Element < XMLElement
|
3
|
+
attr_reader :display_style
|
4
|
+
|
5
|
+
def as_display_style
|
6
|
+
@display_style = true
|
7
|
+
self
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module Variant
|
12
|
+
NORMAL = "normal"
|
13
|
+
BOLD = "bold"
|
14
|
+
BOLD_ITALIC = "bold-italic"
|
15
|
+
def variant=(v)
|
16
|
+
self["mathvariant"] = v
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Align
|
21
|
+
CENTER = "center"
|
22
|
+
LEFT = "left"
|
23
|
+
RIGHT = "right"
|
24
|
+
end
|
25
|
+
|
26
|
+
module Line
|
27
|
+
SOLID = "solid"
|
28
|
+
NONE = "none"
|
29
|
+
end
|
30
|
+
|
31
|
+
class Math < XMLElement
|
32
|
+
def initialize(display_style)
|
33
|
+
super("math", "xmlns"=>"http://www.w3.org/1998/Math/MathML")
|
34
|
+
self[:display] = display_style ? "block" : "inline"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Row < Element
|
39
|
+
def initialize
|
40
|
+
super("mrow")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class None < Element
|
45
|
+
def initialize
|
46
|
+
super("none")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Space < Element
|
51
|
+
def initialize(width)
|
52
|
+
super("mspace", "width"=>width)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Fenced < Element
|
57
|
+
attr_reader :open, :close
|
58
|
+
|
59
|
+
def initialize
|
60
|
+
super("mfenced")
|
61
|
+
end
|
62
|
+
|
63
|
+
def open=(o)
|
64
|
+
o = "" if o.to_s=="." || !o
|
65
|
+
o = "{" if o.to_s=="\\{"
|
66
|
+
self[:open] = MathML.pcstring(o, true)
|
67
|
+
end
|
68
|
+
|
69
|
+
def close=(c)
|
70
|
+
c = "" if c.to_s=="." || !c
|
71
|
+
c = "}" if c.to_s=="\\}"
|
72
|
+
self[:close] = MathML.pcstring(c, true)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Frac < Element
|
77
|
+
def initialize(numerator, denominator)
|
78
|
+
super("mfrac")
|
79
|
+
self << numerator
|
80
|
+
self << denominator
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class SubSup < Element
|
85
|
+
attr_reader :sub, :sup, :body
|
86
|
+
|
87
|
+
def initialize(display_style, body)
|
88
|
+
super("mrow")
|
89
|
+
as_display_style if display_style
|
90
|
+
@body = body
|
91
|
+
end
|
92
|
+
|
93
|
+
def update_name
|
94
|
+
if @sub || @sup
|
95
|
+
name = "m"
|
96
|
+
name << (@sub ? (@display_style ? "under" : "sub") : "")
|
97
|
+
name << (@sup ? (@display_style ? "over" : "sup") : "")
|
98
|
+
else
|
99
|
+
name = "mrow"
|
100
|
+
end
|
101
|
+
self.name = name
|
102
|
+
end
|
103
|
+
private :update_name
|
104
|
+
|
105
|
+
def update_contents
|
106
|
+
contents.clear
|
107
|
+
contents << @body
|
108
|
+
contents << @sub if @sub
|
109
|
+
contents << @sup if @sup
|
110
|
+
end
|
111
|
+
private :update_contents
|
112
|
+
|
113
|
+
def update
|
114
|
+
update_name
|
115
|
+
update_contents
|
116
|
+
end
|
117
|
+
private :update
|
118
|
+
|
119
|
+
def sub=(sub)
|
120
|
+
@sub = sub
|
121
|
+
update
|
122
|
+
end
|
123
|
+
|
124
|
+
def sup=(sup)
|
125
|
+
@sup = sup
|
126
|
+
update
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class Over < Element
|
131
|
+
def initialize(base, over)
|
132
|
+
super("mover")
|
133
|
+
self << base << over
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class Under < Element
|
138
|
+
def initialize(base, under)
|
139
|
+
super("munder")
|
140
|
+
self << base << under
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Number < Element
|
145
|
+
def initialize
|
146
|
+
super("mn")
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class Identifier < Element
|
151
|
+
def initialize
|
152
|
+
super("mi")
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class Operator < Element
|
157
|
+
def initialize
|
158
|
+
super("mo")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class Text < Element
|
163
|
+
def initialize
|
164
|
+
super("mtext")
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
class Sqrt < Element
|
169
|
+
def initialize
|
170
|
+
super("msqrt")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class Root < Element
|
175
|
+
def initialize(index, base)
|
176
|
+
super("mroot")
|
177
|
+
self << base
|
178
|
+
self << index
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
class Table < Element
|
183
|
+
def initialize
|
184
|
+
super("mtable")
|
185
|
+
end
|
186
|
+
|
187
|
+
def set_align_attribute(name, a, default)
|
188
|
+
if a.is_a?(Array) && a.size>0
|
189
|
+
value = ""
|
190
|
+
a.each do |i|
|
191
|
+
value << " "+i
|
192
|
+
end
|
193
|
+
if value =~ /^( #{default})*$/
|
194
|
+
@attributes.delete(name)
|
195
|
+
else
|
196
|
+
@attributes[name] = value.strip
|
197
|
+
end
|
198
|
+
else
|
199
|
+
@attributes.delete(name)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def aligns=(a)
|
204
|
+
set_align_attribute("columnalign", a, Align::CENTER)
|
205
|
+
end
|
206
|
+
|
207
|
+
def vlines=(a)
|
208
|
+
set_align_attribute("columnlines", a, Line::NONE)
|
209
|
+
end
|
210
|
+
|
211
|
+
def hlines=(a)
|
212
|
+
set_align_attribute("rowlines", a, Line::NONE)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
class Tr < Element
|
217
|
+
def initialize
|
218
|
+
super("mtr")
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
class Td < Element
|
223
|
+
def initialize
|
224
|
+
super("mtd")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|