rabbit 0.6.4 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +1 -1
- data/NEWS.en +157 -2
- data/NEWS.ja +153 -1
- data/README.en +8 -1
- data/README.ja +8 -1
- data/Rakefile +4 -1
- data/TODO +17 -0
- data/bin/rabbiter +96 -0
- data/lib/rabbit/element/block-element.rb +0 -2
- data/lib/rabbit/element/block.rb +5 -4
- data/lib/rabbit/element/container-element.rb +2 -1
- data/lib/rabbit/element/description-list.rb +5 -2
- data/lib/rabbit/element/enum-list.rb +4 -0
- data/lib/rabbit/element/image.rb +41 -1
- data/lib/rabbit/element/item-list.rb +3 -0
- data/lib/rabbit/element/method-list.rb +2 -2
- data/lib/rabbit/element/poppler-page.rb +1 -0
- data/lib/rabbit/element/slide-element.rb +1 -0
- data/lib/rabbit/element/slide.rb +1 -1
- data/lib/rabbit/element/table.rb +7 -2
- data/lib/rabbit/element/tag.rb +1 -0
- data/lib/rabbit/element/text-block-element.rb +11 -0
- data/lib/rabbit/element/text-container-element.rb +4 -0
- data/lib/rabbit/element/text.rb +6 -3
- data/lib/rabbit/element/title-slide.rb +10 -10
- data/lib/rabbit/parser/ext/aafigure.rb +31 -0
- data/lib/rabbit/parser/rd.rb +2 -1
- data/lib/rabbit/parser/rd/ext/aafigure.rb +18 -0
- data/lib/rabbit/parser/rd/ext/block-verbatim.rb +27 -1
- data/lib/rabbit/parser/rd/ext/inline-verbatim.rb +16 -22
- data/lib/rabbit/parser/rd/rd2rabbit-lib.rb +8 -2
- data/lib/rabbit/parser/rd/rt/rt2rabbit-lib.rb +7 -1
- data/lib/rabbit/parser/wiki/output.rb +35 -6
- data/lib/rabbit/rabbit.rb +7 -1
- data/lib/rabbit/renderer/display/clutter-embed.rb +2 -0
- data/lib/rabbit/renderer/display/comment-drawing-area.rb +2 -0
- data/lib/rabbit/renderer/print/base.rb +6 -1
- data/lib/rabbit/theme/applier.rb +1 -1
- data/lib/rabbit/theme/background-image-toolkit/background-image-toolkit.rb +85 -0
- data/lib/rabbit/theme/body-background-image/body-background-image.rb +8 -0
- data/lib/rabbit/theme/clear-blue/clear-blue.rb +1 -1
- data/lib/rabbit/theme/default/default.rb +12 -4
- data/lib/rabbit/theme/per-slide-background-image/per-slide-background-image.rb +7 -35
- data/lib/rabbit/theme/table/table.rb +13 -11
- data/lib/rabbit/theme/tag/property.rb +4 -0
- data/lib/rabbit/theme/tag/tag.rb +35 -0
- data/lib/rabbit/theme/title-background-image/title-background-image.rb +19 -17
- data/sample/rabbit-en.rd +89 -1
- data/sample/rabbit.rd +91 -2
- data/sample/table.hiki +34 -0
- metadata +106 -32
@@ -0,0 +1,31 @@
|
|
1
|
+
module Rabbit
|
2
|
+
module Parser
|
3
|
+
module Ext
|
4
|
+
module AAFigure
|
5
|
+
module_function
|
6
|
+
AVAILABLE_OPTIONS = ["linewidth", "foreground", "fill", "background",
|
7
|
+
"option"]
|
8
|
+
def make_image_by_aafigure(path, prop, logger)
|
9
|
+
image_file = Tempfile.new("rabbit-image-aafigure")
|
10
|
+
command = ["aafigure",
|
11
|
+
"--type", "svg",
|
12
|
+
"--encoding", "utf-8",
|
13
|
+
"--output", image_file.path]
|
14
|
+
aafigure_options = []
|
15
|
+
AVAILABLE_OPTIONS.each do |name|
|
16
|
+
command.concat(["--#{name}", prop[name]]) if prop.has_key?(name)
|
17
|
+
end
|
18
|
+
command << path
|
19
|
+
if SystemRunner.run(*command)
|
20
|
+
image_file
|
21
|
+
else
|
22
|
+
format = _("tried aafigure command: %s")
|
23
|
+
additional_info = format % command.inspect
|
24
|
+
raise AAFigureCanNotHandleError.new(command.join(' '),
|
25
|
+
additional_info)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/rabbit/parser/rd.rb
CHANGED
@@ -14,7 +14,8 @@ module Rabbit
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def parse
|
17
|
-
source =
|
17
|
+
source = @source.read.gsub(/\r\n/, "\n")
|
18
|
+
source = "=begin\n#{source}\n=end\n"
|
18
19
|
tree = ::RD::RDTree.new(source)
|
19
20
|
visitor = RD2RabbitVisitor.new(@canvas)
|
20
21
|
visitor.visit(tree)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rabbit/parser/ext/aafigure'
|
2
|
+
|
3
|
+
module Rabbit
|
4
|
+
module Parser
|
5
|
+
class RD
|
6
|
+
module Ext
|
7
|
+
module AAFigure
|
8
|
+
def make_image_by_aafigure(source, visitor)
|
9
|
+
make_image_from_file(source, visitor) do |src_file_path, prop|
|
10
|
+
Parser::Ext::AAFigure.make_image_by_aafigure(src_file_path, prop,
|
11
|
+
visitor)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -10,6 +10,7 @@ require 'rabbit/parser/rd/ext/base'
|
|
10
10
|
require 'rabbit/parser/rd/ext/image'
|
11
11
|
require 'rabbit/parser/rd/ext/enscript'
|
12
12
|
require 'rabbit/parser/rd/ext/tex'
|
13
|
+
require 'rabbit/parser/rd/ext/aafigure'
|
13
14
|
require 'rabbit/parser/rd/ext/anthy'
|
14
15
|
|
15
16
|
module Rabbit
|
@@ -20,6 +21,7 @@ module Rabbit
|
|
20
21
|
include Image
|
21
22
|
include Enscript
|
22
23
|
include TeX
|
24
|
+
include AAFigure
|
23
25
|
include Anthy
|
24
26
|
include GetText
|
25
27
|
|
@@ -38,7 +40,26 @@ module Rabbit
|
|
38
40
|
return nil unless /^(?:image|img)$/i =~ label
|
39
41
|
src, prop = parse_source(source)
|
40
42
|
return nil if prop['src'].nil?
|
41
|
-
|
43
|
+
|
44
|
+
if prop['align'] == "right"
|
45
|
+
body = visitor.current_body
|
46
|
+
if body["background-image"]
|
47
|
+
raise ParseError,
|
48
|
+
_("multiple 'align = right' isn't supported.")
|
49
|
+
end
|
50
|
+
prop.each do |name, value|
|
51
|
+
name = name.gsub(/_/, '-')
|
52
|
+
if name == "src"
|
53
|
+
property_name = "background-image"
|
54
|
+
else
|
55
|
+
property_name = "background-image-#{name}"
|
56
|
+
end
|
57
|
+
body[property_name] = value
|
58
|
+
end
|
59
|
+
:no_element
|
60
|
+
else
|
61
|
+
make_image(visitor, prop['src'], prop)
|
62
|
+
end
|
42
63
|
end
|
43
64
|
|
44
65
|
def ext_block_verb_enscript(label, source, content, visitor)
|
@@ -62,6 +83,11 @@ module Rabbit
|
|
62
83
|
make_image_by_mimeTeX(source, visitor)
|
63
84
|
end
|
64
85
|
|
86
|
+
def ext_block_verb_aafigure(label, source, content, visitor)
|
87
|
+
return nil unless /^aafigure$/i =~ label
|
88
|
+
make_image_by_aafigure(source, visitor)
|
89
|
+
end
|
90
|
+
|
65
91
|
def ext_block_verb_rt(label, source, content, visitor)
|
66
92
|
return nil unless /^rt$/i =~ label
|
67
93
|
unless defined?(RT2RabbitVisitor)
|
@@ -16,7 +16,16 @@ module Rabbit
|
|
16
16
|
Inline = Parser::Ext::Inline
|
17
17
|
|
18
18
|
def default_ext_inline_verbatim(label, source, content, visitor)
|
19
|
-
|
19
|
+
Text.new(source)
|
20
|
+
end
|
21
|
+
|
22
|
+
def apply_inline_verbatim(visitor, text)
|
23
|
+
visitor.apply_to_Verb(::RD::Verb.new(text))
|
24
|
+
end
|
25
|
+
|
26
|
+
def apply_inline_markup(visitor, text)
|
27
|
+
tree = ::RD::RDTree.new("=begin\n#{text}\n=end\n")
|
28
|
+
TextContainer.new(tree.root.children[0].accept(visitor).elements)
|
20
29
|
end
|
21
30
|
|
22
31
|
# def ext_inline_verb_img(label, content, visitor)
|
@@ -32,49 +41,34 @@ module Rabbit
|
|
32
41
|
def ext_inline_verb_del(label, source, content, visitor)
|
33
42
|
label = label.to_s
|
34
43
|
return nil unless /^del:(.*)$/ =~ label
|
35
|
-
DeletedText.new(
|
44
|
+
DeletedText.new(apply_inline_markup(visitor, $1))
|
36
45
|
end
|
37
46
|
|
38
47
|
def ext_inline_verb_sub(label, source, content, visitor)
|
39
48
|
label = label.to_s
|
40
49
|
return nil unless /^sub:(.*)$/ =~ label
|
41
|
-
sub_text = $1
|
42
|
-
if /\A\s*\z/ =~ sub_text
|
43
|
-
sub_text = Text.new(sub_text)
|
44
|
-
else
|
45
|
-
sub_text = visitor.apply_to_Verb(::RD::Verb.new(sub_text))
|
46
|
-
end
|
50
|
+
sub_text = apply_inline_markup(visitor, $1)
|
47
51
|
Inline.sub(sub_text)
|
48
52
|
end
|
49
53
|
|
50
54
|
def ext_inline_verb_sup(label, source, content, visitor)
|
51
55
|
label = label.to_s
|
52
56
|
return nil unless /^sup:(.*)$/ =~ label
|
53
|
-
sup_text = $1
|
54
|
-
if /\A\s*\z/ =~ sup_text
|
55
|
-
sup_text = Text.new(sup_text)
|
56
|
-
else
|
57
|
-
sup_text = visitor.apply_to_Verb(::RD::Verb.new(sup_text))
|
58
|
-
end
|
57
|
+
sup_text = apply_inline_markup(visitor, $1)
|
59
58
|
Inline.sup(sup_text)
|
60
59
|
end
|
61
60
|
|
62
61
|
def ext_inline_verb_note(label, source, content, visitor)
|
63
62
|
label = label.to_s
|
64
63
|
return nil unless /^note:(.*)$/ =~ label
|
65
|
-
target = $1
|
66
|
-
if /^\w+:/ =~ target
|
67
|
-
target = visitor.apply_to_Verb(::RD::Verb.new(target))
|
68
|
-
else
|
69
|
-
target = Text.new(visitor.apply_to_String(target))
|
70
|
-
end
|
64
|
+
target = apply_inline_markup(visitor, $1)
|
71
65
|
Inline.note(target)
|
72
66
|
end
|
73
67
|
|
74
68
|
def ext_inline_verb_lang(label, source, content, visitor)
|
75
69
|
label = label.to_s
|
76
70
|
return nil unless /^lang:([a-z]{2,2}):(.*)$/ =~ label
|
77
|
-
Inline.lang($1,
|
71
|
+
Inline.lang($1, apply_inline_markup(visitor, $2))
|
78
72
|
end
|
79
73
|
|
80
74
|
def ext_inline_verb_wait(label, source, content, visitor)
|
@@ -89,7 +83,7 @@ module Rabbit
|
|
89
83
|
name = $1
|
90
84
|
content = $2
|
91
85
|
if content
|
92
|
-
CustomTag.new(name,
|
86
|
+
CustomTag.new(name, apply_inline_markup(visitor, content))
|
93
87
|
else
|
94
88
|
CustomTag.new(name)
|
95
89
|
end
|
@@ -59,11 +59,12 @@ module Rabbit
|
|
59
59
|
mode = :ignore
|
60
60
|
contents.each do |content|
|
61
61
|
case content
|
62
|
+
when :no_element
|
63
|
+
next
|
62
64
|
when nil
|
63
65
|
mode = :ignore
|
64
66
|
when Slide
|
65
|
-
target =
|
66
|
-
content << target
|
67
|
+
target = content.body
|
67
68
|
@canvas << content
|
68
69
|
mode = :display
|
69
70
|
when TitleSlide
|
@@ -95,6 +96,7 @@ module Rabbit
|
|
95
96
|
@slide = TitleSlide.new(Title.new(title))
|
96
97
|
else
|
97
98
|
@slide = Slide.new(HeadLine.new(title))
|
99
|
+
@slide << Body.new
|
98
100
|
end
|
99
101
|
@foot_texts << []
|
100
102
|
@slides << @slide
|
@@ -277,6 +279,10 @@ module Rabbit
|
|
277
279
|
klass.new(content.collect{|x| x.text}.join(""))
|
278
280
|
end
|
279
281
|
|
282
|
+
def current_body
|
283
|
+
@slide.body
|
284
|
+
end
|
285
|
+
|
280
286
|
private
|
281
287
|
def prepare_footnotes(tree)
|
282
288
|
@footnotes = tree.find_all{|i| i.is_a? ::RD::Footnote}
|
@@ -36,7 +36,13 @@ module Rabbit
|
|
36
36
|
targets.each do |r|
|
37
37
|
row = Element::TableRow.new
|
38
38
|
each_cell(r) do |c|
|
39
|
-
|
39
|
+
tree = ::RD::RDTree.new("=begin\n#{c.value}\n=end\n")
|
40
|
+
if tree.root.children.empty?
|
41
|
+
elements = []
|
42
|
+
else
|
43
|
+
elements = tree.root.children[0].accept(@rd_visitor).elements
|
44
|
+
end
|
45
|
+
cell = cell_class.new(elements)
|
40
46
|
setup_text_align(cell, c.align)
|
41
47
|
row << cell
|
42
48
|
end
|
@@ -5,6 +5,7 @@ require 'rabbit/parser/ext/inline'
|
|
5
5
|
require 'rabbit/parser/ext/image'
|
6
6
|
require 'rabbit/parser/ext/enscript'
|
7
7
|
require 'rabbit/parser/ext/tex'
|
8
|
+
require 'rabbit/parser/ext/aafigure'
|
8
9
|
require 'rabbit/parser/ext/anthy'
|
9
10
|
require 'rabbit/parser/ext/entity'
|
10
11
|
|
@@ -47,6 +48,9 @@ module Rabbit
|
|
47
48
|
[]
|
48
49
|
end
|
49
50
|
|
51
|
+
def current_body
|
52
|
+
@slides.last.body
|
53
|
+
end
|
50
54
|
|
51
55
|
#
|
52
56
|
# Procedures
|
@@ -223,8 +227,7 @@ module Rabbit
|
|
223
227
|
|
224
228
|
@have_table_header = true
|
225
229
|
@table_head << @parent if @parent.parent.nil?
|
226
|
-
|
227
|
-
header = TableHeader.new(content)
|
230
|
+
header = TableHeader.new(item)
|
228
231
|
def header.default_align
|
229
232
|
Pango::Layout::ALIGN_CENTER
|
230
233
|
end
|
@@ -236,8 +239,7 @@ module Rabbit
|
|
236
239
|
|
237
240
|
@have_table_body = true
|
238
241
|
@table_body << @parent if @parent.parent.nil?
|
239
|
-
|
240
|
-
@parent << TableCell.new(content)
|
242
|
+
@parent << TableCell.new(item)
|
241
243
|
end
|
242
244
|
|
243
245
|
def blockquote_open
|
@@ -288,7 +290,9 @@ module Rabbit
|
|
288
290
|
def block_plugin(src)
|
289
291
|
return unless @parent
|
290
292
|
|
291
|
-
|
293
|
+
result = evaluate_block_plugin(src)
|
294
|
+
return if result == :no_element
|
295
|
+
@parent << (result || text("{{#{src}}}"))
|
292
296
|
end
|
293
297
|
|
294
298
|
|
@@ -404,6 +408,7 @@ module Rabbit
|
|
404
408
|
end
|
405
409
|
|
406
410
|
class BlockPlugin
|
411
|
+
include GetText
|
407
412
|
include Element
|
408
413
|
|
409
414
|
def initialize(output)
|
@@ -411,7 +416,23 @@ module Rabbit
|
|
411
416
|
end
|
412
417
|
|
413
418
|
def image(source, props={})
|
414
|
-
|
419
|
+
if props[:align].to_s == "right"
|
420
|
+
body = @output.current_body
|
421
|
+
if body["background-image"]
|
422
|
+
raise ParseError,
|
423
|
+
_("multiple {{image, 'XXX.png', :align => :right}} " + \
|
424
|
+
"isn't supported.")
|
425
|
+
end
|
426
|
+
body["background-image"] = source
|
427
|
+
props.each do |name, value|
|
428
|
+
name = name.to_s.gsub(/_/, '-')
|
429
|
+
value = value.to_s if name == "align"
|
430
|
+
body["background-image-#{name}"] = value
|
431
|
+
end
|
432
|
+
:no_element
|
433
|
+
else
|
434
|
+
Ext::Image.make_image(@output.canvas, source, props)
|
435
|
+
end
|
415
436
|
end
|
416
437
|
alias_method :img, :image
|
417
438
|
|
@@ -453,6 +474,14 @@ module Rabbit
|
|
453
474
|
end
|
454
475
|
end
|
455
476
|
alias_method :mimetex, :mimeTeX
|
477
|
+
|
478
|
+
def aafigure(source, props={})
|
479
|
+
args = [@output.canvas, source]
|
480
|
+
Ext::Image.make_image_from_file(*args) do |src_file_path|
|
481
|
+
args = [src_file_path, props, @output.canvas]
|
482
|
+
[Ext::AAFigure.make_image_by_aafigure(*args), props]
|
483
|
+
end
|
484
|
+
end
|
456
485
|
end
|
457
486
|
end
|
458
487
|
end
|
data/lib/rabbit/rabbit.rb
CHANGED
@@ -8,7 +8,7 @@ require "rabbit/gettext"
|
|
8
8
|
|
9
9
|
module Rabbit
|
10
10
|
|
11
|
-
VERSION = "0.
|
11
|
+
VERSION = "0.9.0"
|
12
12
|
|
13
13
|
TMP_DIR_NAME = ".tmp"
|
14
14
|
|
@@ -84,6 +84,12 @@ module Rabbit
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
+
class AAFigureCanNotHandleError < ImageLoadWithExternalCommandError
|
88
|
+
def initialize(command, additional_info=nil)
|
89
|
+
super("aafigure", command, additional_info)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
87
93
|
class UnknownPropertyError < Error
|
88
94
|
attr_reader :name
|
89
95
|
def initialize(name)
|
@@ -51,7 +51,7 @@ module Rabbit
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def filename
|
54
|
-
@filename ||=
|
54
|
+
@filename ||= default_filename
|
55
55
|
end
|
56
56
|
|
57
57
|
def draw_slide(slide, simulation)
|
@@ -67,6 +67,11 @@ module Rabbit
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def default_filename
|
73
|
+
"#{GLib.filename_from_utf8(@canvas.title.gsub(/\n/, ''))}.pdf"
|
74
|
+
end
|
70
75
|
end
|
71
76
|
end
|
72
77
|
end
|
data/lib/rabbit/theme/applier.rb
CHANGED
@@ -126,7 +126,7 @@ module Rabbit
|
|
126
126
|
|
127
127
|
draw_order = Proc.new do |item, canvas, x, y, w, h, tw, th, layout|
|
128
128
|
first_text = item.elements.first
|
129
|
-
text_height = first_text.
|
129
|
+
text_height = first_text.first_line_height
|
130
130
|
text_height += first_text.padding_top + first_text.padding_bottom
|
131
131
|
adjust_y = ((text_height / 2.0) - (th / 2.0)).ceil
|
132
132
|
|
@@ -0,0 +1,85 @@
|
|
1
|
+
def apply_background_image_property(element, options={})
|
2
|
+
proc_name = options[:proc_name] || "background-image"
|
3
|
+
compute_initial_geometry = options[:compute_initial_geometry]
|
4
|
+
|
5
|
+
element.delete_pre_draw_proc_by_name(proc_name)
|
6
|
+
|
7
|
+
if options.has_key?(:file_name)
|
8
|
+
background_image = options[:file_name]
|
9
|
+
else
|
10
|
+
background_image = element["background-image"]
|
11
|
+
background_image = canvas.full_path(background_image) if background_image
|
12
|
+
end
|
13
|
+
return if background_image.nil?
|
14
|
+
|
15
|
+
if options.has_key?(:properties)
|
16
|
+
properties = options[:properties]
|
17
|
+
else
|
18
|
+
properties = {}
|
19
|
+
element.user_property.each do |name, value|
|
20
|
+
if /\Abackground-image-/ =~ name
|
21
|
+
properties[$POSTMATCH.gsub(/-/, '_')] = value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
image = Image.new(background_image, properties)
|
27
|
+
align = properties["align"] || "center"
|
28
|
+
vertical_align = properties["vertical_align"] || "middle"
|
29
|
+
assign_box = properties["assign_box"]
|
30
|
+
element_margin_right = 0
|
31
|
+
case align
|
32
|
+
when "center"
|
33
|
+
image.horizontal_centering = true
|
34
|
+
end
|
35
|
+
case vertical_align
|
36
|
+
when "middle"
|
37
|
+
image.vertical_centering = true
|
38
|
+
end
|
39
|
+
|
40
|
+
element.add_pre_draw_proc(proc_name) do |canvas, x, y, w, h, simulation|
|
41
|
+
if simulation
|
42
|
+
if compute_initial_geometry
|
43
|
+
_x, _y, _w, _h = compute_initial_geometry.call(canvas, x, y, w, h)
|
44
|
+
else
|
45
|
+
_x, _y, _w, _h = x, y, w, h
|
46
|
+
end
|
47
|
+
|
48
|
+
old_geometry = [_x, _y, _w, _h]
|
49
|
+
image.compile(canvas, _x, _y, _w, _h)
|
50
|
+
if image.do_vertical_centering?
|
51
|
+
adjust_height = ((_h - image.height - image.padding_bottom) / 2.0).ceil
|
52
|
+
if _y + adjust_height > 0
|
53
|
+
_y += adjust_height
|
54
|
+
_h -= adjust_height
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
case align
|
59
|
+
when "right"
|
60
|
+
if assign_box
|
61
|
+
element_margin_right = image.width +
|
62
|
+
image.margin_left + image.margin_right +
|
63
|
+
element.margin_right + element.padding_right
|
64
|
+
element_margin_right += element.parent.margin_right if element.parent
|
65
|
+
end
|
66
|
+
_x = _w - image.width - image.margin_right
|
67
|
+
when "center"
|
68
|
+
end
|
69
|
+
|
70
|
+
if old_geometry != [_x, _y, _w, _h]
|
71
|
+
image.compile(canvas, _x, _y, _w, _h)
|
72
|
+
end
|
73
|
+
|
74
|
+
if image.do_horizontal_centering?
|
75
|
+
image.do_horizontal_centering(canvas, _x, _y, _w, _h)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
image.draw(simulation)
|
79
|
+
[x, y, w - element_margin_right, h]
|
80
|
+
end
|
81
|
+
|
82
|
+
element.add_post_draw_proc(proc_name) do |canvas, x, y, w, h, simulation|
|
83
|
+
[x, y, w + element_margin_right, h]
|
84
|
+
end
|
85
|
+
end
|